package info.touret.winecellar.admin.client;

import info.touret.winecellar.userinfo.client.UserInfoRequest;
import info.touret.winecellar.userinfo.client.UserInfoRequestFactory;
import info.touret.winecellar.userinfo.shared.UserInfoProxy;

import static info.touret.winecellar.dao.client.Constants.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import com.google.gwt.activity.shared.Activity;
import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionModel;
import com.google.web.bindery.requestfactory.shared.EntityProxyChange;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
import com.google.web.bindery.requestfactory.shared.Violation;

public class AdminConsole extends Composite implements
		EntityProxyChange.Handler<UserInfoProxy>, Activity {

	private static AdminConsoleUiBinder uiBinder = GWT
			.create(AdminConsoleUiBinder.class);
	@UiField
	VerticalPanel useradminpanel;
	@UiField
	CellTable<UserInfoProxy> userCellTable = new CellTable<UserInfoProxy>();

	@UiField
	TextBox emailField;
	@UiField
	Button submitButton;
	@UiField
	Button rollbackButton;

	@UiField(provided = true)
	SimplePager pager = new SimplePager(TextLocation.CENTER);

	interface AdminConsoleUiBinder extends UiBinder<Widget, AdminConsole> {
	}

	public AdminConsole() {
		initWidget(uiBinder.createAndBindUi(this));
		requestFactory = GWT.create(UserInfoRequestFactory.class);
		requestFactory.initialize(new SimpleEventBus());
		populateTable();
		createTable();
	}

	private UserInfoRequestFactory requestFactory;

	private Receiver<List<UserInfoProxy>> lastDataReceiver;
	private List<UserInfoProxy> lastData;

	private void populateTable() {
		// provider asynchrone
		AsyncDataProvider<UserInfoProxy> dataProdiver = new AsyncDataProvider<UserInfoProxy>() {
			@Override
			protected void onRangeChanged(HasData<UserInfoProxy> display) {
				// final Range range = display.getVisibleRange();
				UserInfoRequest request = requestFactory.userinfoRequest();
				final int start = display.getVisibleRange().getStart();
				final int displayLength = display.getVisibleRange().getLength();
				Request<List<UserInfoProxy>> getReq = request.findAllUserInfo();
				lastDataReceiver = new Receiver<List<UserInfoProxy>>() {
					@Override
					public void onSuccess(List<UserInfoProxy> response) {
						int end = (start + displayLength) >= response.size() ? response
								.size() : (start + response.size());
						userCellTable.setVisibleRange(start, end);
						updateRowCount(response.size(), true);
						updateRowData(start, response);
						lastData = new ArrayList<UserInfoProxy>(response);
					}
				};
				getReq.fire(lastDataReceiver);
			}
		};
		dataProdiver.addDataDisplay(userCellTable);
	}

	@UiHandler("updateButton")
	void onUpdatebuttonClick(ClickEvent event) {
		populateTable();
	}

	/**
	 * Provider des cles primaires des bouteilles presentes dans le tableau
	 */
	private static final ProvidesKey<UserInfoProxy> KEY_PROVIDER = new ProvidesKey<UserInfoProxy>() {
		public Object getKey(UserInfoProxy item) {
			return item.getId();
		}
	};

	/**
	 * Cree le tableau principal
	 */
	private void createTable() {
		/*
		 * Ce tableau gere la selection via un checkbox selection model Un CB
		 * est necessaire pour la suppression
		 */
		final SelectionModel<UserInfoProxy> checkboxSelectionModel = new MultiSelectionModel<UserInfoProxy>(
				KEY_PROVIDER);

		userCellTable.setSelectionModel(checkboxSelectionModel,
				DefaultSelectionEventManager
						.<UserInfoProxy> createCheckboxManager());

		/**
		 * definitions des colonnes
		 * 
		 * */
		Column<UserInfoProxy, Boolean> checkColumn = new Column<UserInfoProxy, Boolean>(
				new CheckboxCell(true, false)) {
			@Override
			public Boolean getValue(UserInfoProxy object) {
				return checkboxSelectionModel.isSelected(object);
			}
		};
		userCellTable
				.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant(""));

		final Receiver<Void> updateReceiver = new Receiver<Void>() {
			@Override
			public void onSuccess(Void response) {
				// rien
			}

			@Override
			public void onFailure(ServerFailure error) {
				super.onFailure(error);
				Window.alert("La modification a echouee");
			}

			@Override
			public void onViolation(Set<Violation> errors) {
				Window.alert("La modification a echouee : Parametres incorrects");
			}
		};

		// NOM
		final EditTextCell nameCell = new EditTextCell();
		Column<UserInfoProxy, String> nameColumn = new Column<UserInfoProxy, String>(
				nameCell) {
			@Override
			public String getValue(UserInfoProxy object) {
				return object.getNickname();
			}

		};
		// nameColumn.setSortable(true);
		nameColumn.setFieldUpdater(new FieldUpdater<UserInfoProxy, String>() {
			@Override
			public void update(int index, UserInfoProxy object, String value) {
				// nameCell.clearViewData(KEY_PROVIDER.getKey(object));

				UserInfoRequest request = requestFactory.userinfoRequest();
				UserInfoProxy proxy = request.edit(object);
				proxy.setNickname(value);
				request.update().using(proxy).fire(updateReceiver);
				return;
			}
		});
		nameColumn.setSortable(true);
		userCellTable.addColumn(nameColumn, "Nickname");

		// nom de la bouteille
		final EditTextCell emailCell = new EditTextCell();
		Column<UserInfoProxy, String> emailColumn = new Column<UserInfoProxy, String>(
				emailCell) {
			@Override
			public String getValue(UserInfoProxy object) {
				return object.getEmailAddress() == null ? "" : object
						.getEmailAddress();
			}

		};
		// appellation
		emailColumn.setFieldUpdater(new FieldUpdater<UserInfoProxy, String>() {
			@Override
			public void update(int index, UserInfoProxy object, String value) {
				// nameCell.clearViewData(KEY_PROVIDER.getKey(object));

				UserInfoRequest request = requestFactory.userinfoRequest();
				UserInfoProxy proxy = request.edit(object);
				proxy.setEmailAddress(value);
				request.update().using(proxy).fire(updateReceiver);
				return;
			}
		});
		emailColumn.setSortable(true);
		userCellTable.addColumn(emailColumn, "E-Mail");

		// producteur
		final EditTextCell gdatatokencell = new EditTextCell();
		Column<UserInfoProxy, String> gdatatokenColumn = new Column<UserInfoProxy, String>(
				gdatatokencell) {
			@Override
			public String getValue(UserInfoProxy object) {
				return object.getGdatatoken();
			}

		};
		// nameColumn.setSortable(true);
		gdatatokenColumn
				.setFieldUpdater(new FieldUpdater<UserInfoProxy, String>() {
					@Override
					public void update(int index, UserInfoProxy object,
							String value) {
						if (!"".equals(value)) {
							UserInfoRequest request = requestFactory
									.userinfoRequest();
							UserInfoProxy proxy = request.edit(object);
							proxy.setGdatatoken(value);
							request.update().using(proxy).fire(updateReceiver);
						}
						return;
					}
				});
		gdatatokenColumn.setSortable(true);
		userCellTable.addColumn(gdatatokenColumn, "Token Google");

		pager.setDisplay(userCellTable);
		pager.setPageSize(PAGE_SIZE);
	}

	/**
	 * Supprime la ligne selectionnee du tableau
	 * 
	 * @param event
	 */
	@UiHandler("deleteButton")
	void onDeleteButtonClick(ClickEvent event) {
		deleteSelectedItems();
	}

	/**
	 * @TODO factoriser
	 */
	private void deleteSelectedItems() {
		if (lastDataReceiver != null) {
			UserInfoRequest req = requestFactory.userinfoRequest();
			for (UserInfoProxy current : lastData)
				if (userCellTable.getSelectionModel().isSelected(current)) {
					UserInfoProxy toremove = req.edit(current);
					req.remove().using(toremove);
				}
			req.fire(new Receiver<Void>() {
				@Override
				public void onSuccess(Void response) {
					populateTable();
				}
			});
		}
	}

	@UiField
	Button updateButton;

	@UiField
	Button deleteButton;

	/*
	 * Styles
	 */
	interface SelectionStyle extends CssResource {
		String selectedRow();
	}

	interface TableResources extends CellTable.Resources {
		@Source({ CellTable.Style.DEFAULT_CSS, "AdminListCellTable.css" })
		TableStyle cellTableStyle();
	}

	/**
	 * The styles applied to the table.
	 */
	interface TableStyle extends CellTable.Style {
	}

	@Override
	public String mayStop() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCancel() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub

	}

	@Override
	public void start(AcceptsOneWidget panel, EventBus eventBus) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProxyChange(EntityProxyChange<UserInfoProxy> event) {
		// TODO Auto-generated method stub

	}

	@UiHandler("submitButton")
	void onSubmitButtonClick(ClickEvent event) {
		UserInfoRequest request = requestFactory.userinfoRequest();
		UserInfoProxy userinfo = request.create(UserInfoProxy.class);
		userinfo.setEmailAddress(emailField.getText());
		request.persist().using(userinfo).fire(new Receiver<Void>() {
			@Override
			public void onSuccess(Void response) {
				Window.alert("Insertion OK");
				clearform();
			}

			@Override
			public void onFailure(ServerFailure error) {
				// TODO Auto-generated method stub
				super.onFailure(error);
				Window.alert("Erreur");
			}

		});
	}

	@UiHandler("rollbackButton")
	void onRollbackButtonClick(ClickEvent event) {
		clearform();
	}

	private void clearform() {
		emailField.setText("");
	}

	
}
